package cn.edu.zufe.mjt.binary;

import cn.edu.zufe.mjt.validator.Validator;

import java.util.Arrays;

/**
 * 二分查找：前驱后继问题
 * 问题描述：给定一个升序数组 arr ，长度为 n，以及 Q 次询问。每次询问都会给出一个目标值 target，
 *         对于每个目标值，找出数组中比目标值小的最大值 max_val 和比目标值大的最小值 min_val，
 *         如果不存在则都输出 -1。
 */
public class PrecursorFollowedQuestions {
    public static void main(String[] args) {
        int[] ints = Validator.randomArray(10, 20);
        Arrays.sort(ints);
        int[] targets = Validator.randomArray(4, 20);
        System.out.println("ints = " + Arrays.toString(ints));
        System.out.println("targets = " + Arrays.toString(targets));
        for (int target : targets) {
            int max_val = findPre(ints, target);
            int min_val = findFollow(ints, target);
            System.out.println("target: " + target + " max_val: " + ints[max_val] + " min_val: " + ints[min_val]);
        }
    }

    public static int findPre(int[] arr, int target) {
        // 划定前缀 P
        // 考虑终局： 让 L 停留在 P 的下一个位置 mid < target 时， L = mid + 1；让 R 停留在 P 的最后一个位置 mid ≥ target 时，R = mid - 1。
        // 最终返回的是 R
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        if (right < 0) {
            return -1;
        } else {
            return right;
        }
    }

    public static int findFollow(int[] arr, int target) {
        // 划定后缀 F
        // 考虑终局： 让 L 停留在 F 的上一个位置 mid > target 时，L = mid + 1；让 R 停留在 F 的第一个位置 mid ≤ target 时，R = mid - 1。
        // 最终返回的是 L
        int left = 0, right = arr.length - 1;
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] <= target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        if (left >= arr.length) {
            return -1;
        } else {
            return left;
        }
    }
}
